package goxele

import (
	"encoding/binary"
	"fmt"
	"math"
	"strings"
)

type InstrumentPoint [8]byte

func (f InstrumentPoint) String() string {
	return fmt.Sprintf("%x", f.Uint64())
}
func (f InstrumentPoint) Uint64() uint64 {
	return binary.LittleEndian.Uint64(f[:])
}

type Float [8]byte

func (f Float) String() string {
	return fmt.Sprintf("%f", f.Float64())
}
func (f Float) Float64() float64 {
	bits := binary.LittleEndian.Uint64(f[:])
	return math.Float64frombits(bits)
}
func (f Float) FromFloat64(value float64) Float {
	bs := make([]byte, 8)
	binary.LittleEndian.PutUint64(bs, math.Float64bits(value))
	copy(f[:], bs)
	return f
}

type Uint32 [4]byte

func (u Uint32) String() string {
	return fmt.Sprintf("%d", u.Uint32())
}
func (u Uint32) Uint32() uint32 {
	return binary.LittleEndian.Uint32(u[:])
}
func (u Uint32) FromUint32(value uint32) Uint32 {
	binary.LittleEndian.PutUint32(u[:], value)
	return u
}

type XTFAccountID [20]byte

func (e XTFAccountID) String() string {
	return strings.TrimRight(string(e[:]), "\x00")
}

type XTFDate [9]byte

func (e XTFDate) String() string {
	return strings.TrimRight(string(e[:]), "\x00")
}

type XTFTime [9]byte

func (e XTFTime) String() string {
	return strings.TrimRight(string(e[:]), "\x00")
}

type XTFInstrumentID [32]byte

func (e XTFInstrumentID) String() string {
	return strings.TrimRight(string(e[:]), "\x00")
}

type XTFExchangeID [12]byte

func (e XTFExchangeID) String() string {
	return strings.TrimRight(string(e[:]), "\x00")
}

// 买卖方向
type XTFDirection byte

const XFT_D_Buy XTFDirection = 1
const XFT_D_Sell XTFDirection = 2
const XFT_D_Invalid XTFDirection = 255

var mpXTFDirection = map[XTFDirection]string{XFT_D_Buy: "XFT_D_Buy", XFT_D_Sell: "XFT_D_Sell", XFT_D_Invalid: "XFT_D_Invalid"}

func (e XTFDirection) String() string {
	if s, ok := mpXTFDirection[e]; ok {
		return s[strings.LastIndex(s, "_")+1:]
	}
	return string(e) + "值未定义"
}

// 开平标志
type XTFOffsetFlag byte

const XTF_OF_Open XTFOffsetFlag = 0           ///< 开仓
const XTF_OF_Close XTFOffsetFlag = 1          ///< 平仓
const XTF_OF_ForceClose XTFOffsetFlag = 2     ///< 强平（暂不支持）
const XTF_OF_CloseToday XTFOffsetFlag = 3     ///< 平今
const XTF_OF_CloseYesterday XTFOffsetFlag = 4 ///< 平昨
const XTF_OF_Invalid XTFOffsetFlag = 255      ///< 无效值
var mpXTFOffsetFlag = map[XTFOffsetFlag]string{XTF_OF_Open: "XTF_OF_Open", XTF_OF_Close: "XTF_OF_Close", XTF_OF_ForceClose: "XTF_OF_ForceClose", XTF_OF_CloseToday: "XTF_OF_CloseToday", XTF_OF_CloseYesterday: "XTF_OF_CloseYesterday", XTF_OF_Invalid: "XTF_OF_Invalid"}

func (e XTFOffsetFlag) String() string {
	if s, ok := mpXTFOffsetFlag[e]; ok {
		return s[strings.LastIndex(s, "_")+1:]
	}
	return string(e) + "值未定义"
}

// 报单类型
type XTFOrderType uint8

const XTF_ODT_Limit XTFOrderType = 0     ///< GFD报单（限价）
const XTF_ODT_FAK XTFOrderType = 1       ///< FAK报单（限价）
const XTF_ODT_FOK XTFOrderType = 2       ///< FOK报单（限价）
const XTF_ODT_Market XTFOrderType = 3    ///< 市价报单（暂不支持）
const XTF_ODT_Invalid XTFOrderType = 255 ///< 无效值
var mpXTFOrderType = map[XTFOrderType]string{XTF_ODT_Limit: "XTF_ODT_Limit", XTF_ODT_FAK: "XTF_ODT_FAK", XTF_ODT_FOK: "XTF_ODT_FOK", XTF_ODT_Market: "XTF_ODT_Market", XTF_ODT_Invalid: "XTF_ODT_Invalid"}

func (e XTFOrderType) String() string {
	if s, ok := mpXTFOrderType[e]; ok {
		return s[strings.LastIndex(s, "_")+1:]
	}
	return string(e) + "值未定义"
}

// 报单标志
type XTFOrderFlag uint8

const XTF_ODF_Normal XTFOrderFlag = 0          ///< 普通报单
const XTF_ODF_CombinePosition XTFOrderFlag = 1 ///< 组合持仓
const XTF_ODF_Warm XTFOrderFlag = 254          ///< 预热报单
const XTF_ODF_Invalid XTFOrderFlag = 255       ///< 无效值
var mpXTFOrderFlag = map[XTFOrderFlag]string{XTF_ODF_Normal: "XTF_ODF_Normal", XTF_ODF_CombinePosition: "XTF_ODF_CombinePosition", XTF_ODF_Warm: "XTF_ODF_Warm", XTF_ODF_Invalid: "XTF_ODF_Invalid"}

func (e XTFOrderFlag) String() string {
	if s, ok := mpXTFOrderFlag[e]; ok {
		return s[strings.LastIndex(s, "_")+1:]
	}
	return string(e) + "值未定义"
}

// 席位选择
type XTFChannelSelectionType uint8

const XTF_CS_Auto XTFChannelSelectionType = 0    ///< 不指定交易所席位链接
const XTF_CS_Fixed XTFChannelSelectionType = 1   ///< 指定交易所席位链接
const XTF_CS_Unknown XTFChannelSelectionType = 9 ///< 历史报单回报，无法确认报单通道选择类型
var mpXTFChannelSelectionType = map[XTFChannelSelectionType]string{XTF_CS_Auto: "XTF_CS_Auto", XTF_CS_Fixed: "XTF_CS_Fixed", XTF_CS_Unknown: "XTF_CS_Unknown"}

func (e XTFChannelSelectionType) String() string {
	if s, ok := mpXTFChannelSelectionType[e]; ok {
		return s[strings.LastIndex(s, "_")+1:]
	}
	return string(e) + "值未定义"
}

// 报单状态
type XTFOrderStatus uint8

const XTF_OS_Queuing XTFOrderStatus = 2    ///< 报单未成交，进入队列等待撮合，IOC订单无此状态
const XTF_OS_Canceled XTFOrderStatus = 3   ///< 报单已被撤销，可能是客户主动撤销，也可能是IOC报单被交易所系统自动撤销
const XTF_OS_PartTraded XTFOrderStatus = 4 ///< 部分成交
const XTF_OS_AllTraded XTFOrderStatus = 5  ///< 完全成交
const XTF_OS_Rejected XTFOrderStatus = 6   ///< 报单被柜台或交易所拒绝，错误码通过onOrder事件的errorCode参数返回，根据API手册或者官方文档平台错误码说明得到具体原因
const XTF_OS_Invalid XTFOrderStatus = 255  ///< 无效值

var mpXTFOrderStatus = map[XTFOrderStatus]string{XTF_OS_Queuing: "XTF_OS_Queuing", XTF_OS_Canceled: "XTF_OS_Canceled", XTF_OS_PartTraded: "XTF_OS_PartTraded", XTF_OS_AllTraded: "XTF_OS_AllTraded", XTF_OS_Rejected: "XTF_OS_Rejected", XTF_OS_Invalid: "XTF_OS_Invalid"}

func (e XTFOrderStatus) String() string {
	if s, ok := mpXTFOrderStatus[e]; ok {
		return s[strings.LastIndex(s, "_")+1:]
	}
	return string(e) + "值未定义"
}

// 报单操作类型
type XTFOrderActionType uint8

const XTF_OA_Insert XTFOrderActionType = 1    ///< 插入报单
const XTF_OA_Cancel XTFOrderActionType = 2    ///< 撤销报单
const XTF_OA_Suspend XTFOrderActionType = 3   ///< 挂起报单（暂未使用）
const XTF_OA_Resume XTFOrderActionType = 4    ///< 恢复报单（暂未使用）
const XTF_OA_Update XTFOrderActionType = 5    ///< 更新报单（暂未使用）
const XTF_OA_Return XTFOrderActionType = 9    ///< 报单回报
const XTF_OA_Invalid XTFOrderActionType = 255 ///< 无效的报单操作
var mpXTFOrderActionType = map[XTFOrderActionType]string{XTF_OA_Insert: "XTF_OA_Insert", XTF_OA_Cancel: "XTF_OA_Cancel", XTF_OA_Suspend: "XTF_OA_Suspend", XTF_OA_Resume: "XTF_OA_Resume", XTF_OA_Update: "XTF_OA_Update", XTF_OA_Return: "XTF_OA_Return", XTF_OA_Invalid: "XTF_OA_Invalid"}

func (e XTFOrderActionType) String() string {
	if s, ok := mpXTFOrderActionType[e]; ok {
		return s[strings.LastIndex(s, "_")+1:]
	}
	return string(e) + "值未定义"
}

// 期权类型
type XTFOptionsType uint8

const XTF_OT_NotOptions XTFOptionsType = 0  ///< 非期权
const XTF_OT_CallOptions XTFOptionsType = 1 ///< 看涨
const XTF_OT_PutOptions XTFOptionsType = 2  ///< 看跌
var mpXTFOptionsType = map[XTFOptionsType]string{XTF_OT_NotOptions: "XTF_OT_NotOptions", XTF_OT_CallOptions: "XTF_OT_CallOptions", XTF_OT_PutOptions: "XTF_OT_PutOptions"}

func (e XTFOptionsType) String() string {
	if s, ok := mpXTFOptionsType[e]; ok {
		return s[strings.LastIndex(s, "_")+1:]
	}
	return string(e) + "值未定义"
}

// 合约状态
type XTFInstrumentStatus uint8

const XTF_IS_BeforeTrading XTFInstrumentStatus = 0         ///< 开盘前
const XTF_IS_NoTrading XTFInstrumentStatus = 1             ///< 非交易
const XTF_IS_Continuous XTFInstrumentStatus = 2            ///< 连续交易
const XTF_IS_AuctionOrdering XTFInstrumentStatus = 3       ///< 集合竞价报单
const XTF_IS_AuctionBalance XTFInstrumentStatus = 4        ///< 集合竞价价格平衡
const XTF_IS_AuctionMatch XTFInstrumentStatus = 5          ///< 集合竞价撮合
const XTF_IS_Closed XTFInstrumentStatus = 6                ///< 收盘
const XTF_IS_TransactionProcessing XTFInstrumentStatus = 7 ///< 交易业务处理
const XTF_IS_TransactionMatchPause XTFInstrumentStatus = 8 ///< 集合竞价暂停
const XTF_IS_TransactionTradePause XTFInstrumentStatus = 9 ///< 连续交易暂停
const XTF_IS_Alarm XTFInstrumentStatus = 10                ///< 自动转换报警
const XTF_IS_Invalid XTFInstrumentStatus = 255             ///< 无效值
var mpXTFInstrumentStatus = map[XTFInstrumentStatus]string{XTF_IS_BeforeTrading: "XTF_IS_BeforeTrading", XTF_IS_NoTrading: "XTF_IS_NoTrading", XTF_IS_Continuous: "XTF_IS_Continuous", XTF_IS_AuctionOrdering: "XTF_IS_AuctionOrdering", XTF_IS_AuctionBalance: "XTF_IS_AuctionBalance", XTF_IS_AuctionMatch: "XTF_IS_AuctionMatch", XTF_IS_Closed: "XTF_IS_Closed", XTF_IS_TransactionProcessing: "XTF_IS_TransactionProcessing", XTF_IS_TransactionMatchPause: "XTF_IS_TransactionMatchPause", XTF_IS_TransactionTradePause: "XTF_IS_TransactionTradePause", XTF_IS_Alarm: "XTF_IS_Alarm", XTF_IS_Invalid: "XTF_IS_Invalid"}

func (e XTFInstrumentStatus) String() string {
	if s, ok := mpXTFInstrumentStatus[e]; ok {
		return s[strings.LastIndex(s, "_")+1:]
	}
	return string(e) + "值未定义"
}

type XTFAccount struct {
	AccountID        XTFAccountID ///< 账户编码
	PreBalance       Float        ///< 日初资金
	StaticBalance    Float        ///< 静态权益
	DeliveryMargin   Float        ///< 交割保证金
	Deposit          Float        ///< 今日入金
	Withdraw         Float        ///< 今日出金
	Margin           Float        ///< 占用保证金，期权空头保证金目前支持昨结算价或报单价计算。
	FrozenMargin     Float        ///< 冻结保证金
	Premium          Float        ///< 权利金
	FrozenPremium    Float        ///< 冻结权利金
	Commission       Float        ///< 手续费
	FrozenCommission Float        ///< 冻结手续费
	Balance          Float        ///< 动态权益：静态权益+持仓亏损+平仓盈亏-手续费+权利金
	///< 其中：
	///< - 持仓盈亏出现亏损时为负数，计入动态权益与可用资金；
	///< - 持仓盈亏盈利时为正数，不计入动态权益与可用。
	Available Float ///< 可用资金：动态权益-占用保证金-冻结保证金-交割保证金-冻结权利金-冻结手续费
	///< 其中：占用保证金包含期权与期货
	AvailableRatio    Float ///< 资金可用限度
	PositionProfit    Float ///< 持仓盈亏，所有合约的持仓盈亏之和
	CloseProfit       Float ///< 平仓盈亏，所有合约的平仓盈亏之和
	LastLocalOrderID  int32 ///< 用户最后一次报单的本地编号
	LastLocalActionID int32 ///< 用户最后一次撤单的本地编号
}

type XTFInstrument struct {
	InstrumentID         XTFInstrumentID     ///< 合约代码
	InstrumentIndex      Uint32              ///< 合约序号
	DeliveryYear         int                 ///< 交割年份
	DeliveryMonth        int                 ///< 交割月份
	MaxMarketOrderVolume int                 ///< 市价报单的最大报单量
	MinMarketOrderVolume int                 ///< 市价报单的最小报单量
	MaxLimitOrderVolume  int                 ///< 限价报单的最大报单量
	MinLimitOrderVolume  int                 ///< 限价报单的最小报单量
	PriceTick            Float               ///< 最小变动价位
	Multiple             int                 ///< 合约数量乘数
	OptionsType          XTFOptionsType      ///< 期权类型
	ExpireDate           XTFDate             ///< 合约到期日，字符串格式：20220915
	SingleSideMargin     bool                ///< 是否单边计算保证金
	Status               XTFInstrumentStatus ///< 当前状态
}

type XTFInputOrder struct {
	LocalOrderID Uint32 //////< 本地报单编号（用户）
	///< 本地报单编号需要由用户保证唯一性，用于本地存储索引。
	///< 注意不能与柜台保留的几个特殊ID冲突：
	///< 1. 非本柜台报单固定为0x88888888；
	///< 2. 柜台清流启动后的历史报单固定为0xd8888888；
	///< 3. 柜台平仓报单固定为0xe8888888；
	///< 为保证报单性能，API不做本地报单编号重复的校验。
	///< 如果API发生了断线重连，在历史流水追平之后，请继续保持后续本地报单编号与历史报单编号的唯一性。
	///< 如果不能保证本地报单编号的唯一性，请不要使用API的订单管理功能。
	///< API允许客户端使用同一用户名/口令多次登录，但客户端需要使用某种机制确保本地报单编号不发生重复。
	///< 比如：（奇偶交替、分割号段）+单向递增。

	Direction            XTFDirection            ///< 买卖方向
	OffsetFlag           XTFOffsetFlag           ///< 开平仓标志
	OrderType            XTFOrderType            ///< 限价/FAK/市价类型
	OrderPrice           Float                   ///<  报单价格
	OrderVolume          Uint32                  ///<  报单数量
	OrderMinVolume       Uint32                  ///<  最小成交数量
	ChannelSelectionType XTFChannelSelectionType ///< 席位连接选择
	ChannelID            uint8                   ///< 席位连接编号，0xFF表示无效值
	OrderFlag            XTFOrderFlag            ///< 报单标志
	Instrument           [8]byte                 // 合约指针
}

type XTFExchange struct {
	ExchangeID   XTFExchangeID ///< 交易所编码，字符串。比如：CFFEX，SHFE，DCE，CZCE等
	ClientIndex  uint8         ///< 裸协议报单需要使用该字段，每个交易所对应的值不同。
	ClientToken  Uint32        ///< 裸协议报单需要使用该字段，每个交易所对应的值不同。
	TradingDay   XTFDate       ///< 交易日，整数字符串。比如：20220915
	HasChannelIP bool          ///< 是否支持席位编号IP地址查询，true表示支持IP地址查询
}

type XTFOrder struct {
	SysOrderID   int32 ///< 柜台流水号
	LocalOrderID int32 ///< 用户填写的本地报单号，必须保证唯一性，否则会产生回报错误
	///< 错误为1172“请求中的报单编号不存在”时，返回0，其他情况返回订单真实编号
	///< 保留的特殊本地单号：
	///< 1. 非本柜台报单固定为0x88888888；
	///< 2. 柜台清流启动后的历史报单固定为0xd8888888；
	///< 3. 柜台平仓报单固定为0xe8888888；
	ExchangeOrderID      int64                   ///< 交易所报单编号
	Direction            XTFDirection            ///< 买卖方向
	OffsetFlag           XTFOffsetFlag           ///< 开平仓标志
	OrderPrice           Float                   ///<  报单价格
	OrderVolume          Uint32                  ///<  报单数量
	OrderMinVolume       Uint32                  ///<  最小成交数量
	TotalTradedVolume    Uint32                  ///<  报单累计已成交数量
	OrderType            XTFOrderType            ///< 限价/FAK/市价类型
	OrderFlag            XTFOrderFlag            ///< 报单标志
	ChannelSelectionType XTFChannelSelectionType ///< 席位连接选择
	ChannelID            uint8                   ///< 席位连接编号，0xFF表示无效值
	RealChannelID        uint8                   ///< 实际席位连接编号，由柜台返回，0xFF表示无效值
	OrderStatus          XTFOrderStatus          ///< 报单状态
	InsertDate           XTFDate                 ///< 报单插入日期，字符串格式：20220915
	InsertTime           XTFTime                 ///< 报单插入时间，字符串格式：10:20:30
	UpdateTime           XTFTime                 ///< 报单更新时间，字符串格式：10:20:30
	CancelTime           XTFTime                 ///< 报单撤单时间，字符串格式：10:20:boolisHistory 30
	IsHistory            bool                    ///< 回报链路断开重连后或者程序重启后，客户端API会自动进行流水重构，
	///< 在追平服务器流水之前收到的报单回报，该字段为true。追平流水之后，该字段为false。
	///< 如对流水重构的回报不需要特殊处理，可不用处理该字段。
	IsSuspende bool               ///< 报单是否挂起（暂未使用）
	Instrument InstrumentPoint    ///< 所属XTFInstrument的指针。如果报单传入的合约不存在，那么合约对象指针可能为空。
	ActionType XTFOrderActionType ///< 报单对象对应的操作类型（比如：报单、撤单、挂起、激活等），只读字段，外部调用不需要设置该字段。
}

type XTFTrade struct {
	TradeID    int64         ///< 交易所成交编码
	TradePrice Float         ///< 成交价格
	RadeVolume Uint32        ///< 本次回报已成交数量
	Margin     Float         ///< 该字段已废弃
	Commission Float         ///< 本次回报已成交手数产生的手续费
	TradeTime  XTFTime       ///< 报单成交时间，字符串格式：10:20:30
	Direction  XTFDirection  ///< 买卖方向
	OffsetFlag XTFOffsetFlag ///< 开平仓标志
	IsHistory  bool          ///< 回报链路断开重连后或者程序重启后，客户端API会自动进行流水重构，
	///< 在追平服务器流水之前收到的成交回报，该字段为true。追平流水之后，该字段为false。
	///< 如对流水重构的回报不需要特殊处理，可不用处理该字段。
	Orde      uintptr ///< 所属XTFOrder的指针
	MatchTrad uintptr ///< 对手成交回报，如果不为空则表明自成交
}

type XTFMarketData struct {
	TradingDay         int32 ///< 交易日
	PreSettlementPrice Float ///< 前结算价
	PreClosePrice      Float ///< 前收盘价
	PreOpenInterest    Float ///< 前持仓量（暂未使用）
	UpperLimitPrice    Float ///< 涨停价
	LowerLimitPrice    Float ///< 跌停价
	LastPrice          Float ///< 最新价（接入外部行情后有效）
	BidPrice           Float ///< 买入价。为零代表无买入价（接入外部行情后有效）
	BidVolume          int32 ///< 买入量。为零代表无买入价（接入外部行情后有效）
	AskPrice           Float ///< 卖出价。为零代表无卖出价（接入外部行情后有效）
	AskVolume          int32 ///< 卖出量。为零代表无卖出价（接入外部行情后有效）
	Volume             int32 ///< 成交量（暂未使用）
	SnapTime           int32 ///< 时间戳（暂未使用）
	Turnover           Float ///< 成交金额（暂未使用）
	OpenInterest       Float ///< 持仓量（暂未使用）
	AveragePrice       Float ///< 行情均价（暂未使用）
}

type XTFEvent struct {
	TradingDay [9]byte   ///< 通知事件日期(交易日)
	EventTime  [9]byte   ///< 通知事件时间
	EventType  int32     ///< 通知事件类型
	EventID    int32     ///< 通知事件ID
	EventLen   int32     ///< 通知事件数据长度
	EventData  [256]byte ///< 通知事件的数据
	Reserve    [2]byte   ///< 预留字段
}
